package com.ruoyi.framework.web.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.common.core.domain.model.LoginAppUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.user.service.IAppUserService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 登录校验方法
 *
 * @author ruoyi
 */
@Slf4j
@Component
public class AppLoginService {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private AppTokenService appTokenService;
    @Resource
    private IAppUserService appUserSevice;
    @Resource
    private WeChatUserInfoUtilService weChatUserInfoUtilService;

    @Value("${wx.minApp.appId}")
    private String appId;
    @Value("${wx.minApp.appSecret}")
    private String appSecret;

    /**
     * 登录验证
     *
     * @param username 用户名
     * @param password 密码
     * @return 结果
     */
    public String login(String username, String password) {
        AppUser appUser = appUserSevice.selectAppUserByUserName(username);
        if (appUser == null) {
            throw new ServiceException("用户不存在");
        }
        //判断用户是否停用
        if (appUser.getStatus() == 1) {
            throw new ServiceException("当前用户已停用，请联系管理员");
        }
        if (!appUserSevice.checkPassword(password, appUser.getSalt(), appUser.getPassword())) {
            throw new ServiceException("密码不正确");
        }
        LoginAppUser loginAppUser = new LoginAppUser(appUser.getUserId(), appUser);
        recordLoginInfo(loginAppUser.getUserId());
        // 生成token
        return appTokenService.createAppToken(loginAppUser);
    }

    /**
     * 小程序登录
     *
     * @param code
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String minLogin(String code) {
        log.info("小程序登录前端: {}", code);
        //1根据code执行小程序登录获取 openId
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
        String replaceUrl = url.replace("{0}", appId).replace("{1}", appSecret).replace("{2}", code);
        logger.info("小程序登录获取 openId URL: {}", replaceUrl);
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(replaceUrl));
        if (jsonObject.get("errcode") != null) {
            throw new ServiceException(String.format("获取微信授权信息失败，错误编码：%s，错误信息：%s", String.valueOf(jsonObject.get("errcode")), (String) jsonObject.get("errmsg")));
        }
//        logger.info("小程序登录获取 openId: {}", jsonObject.toJSONString());
//        JSONObject accessToken = weChatUserInfoUtilService.getAccessToken(appId, appSecret);
//        logger.info("小程序登录获取 accessToken: {}", accessToken.toJSONString());
//        JSONObject phoneNumber = weChatUserInfoUtilService.getPhoneNumber(code, accessToken.getString("access_token"));
//        JSONObject userInfo = weChatUserInfoUtilService.getUserInfo(jsonObject.getString("openid"), accessToken.getString("access_token"));
//        logger.info("根据openId登录获取用户信息: {}", JSON.toJSON(userInfo));
        //2根据openId判断用户是否存在 不存在自动注册 openId对应数据库表user_name
        AppUser appUser = appUserSevice.selectAppUserByOpenId(String.valueOf(jsonObject.get("openid")));
        if (appUser == null) {
            appUser = new AppUser();
            appUser.setUserId(IdWorker.getId());
            appUser.setUserName(String.valueOf(jsonObject.get("openid")));
            appUser.setNickName("微信用户");
            appUser.setOpenId(String.valueOf(jsonObject.get("openid")));
            appUser.setCreateBy(DateUtils.dateTimeNow());
            appUser.setStatus(0);
            appUserSevice.insertAppUser(appUser);
        }
        //判断用户是否停用
        if (appUser.getStatus() == 1) {
            throw new ServiceException("当前用户已停用，请联系管理员");
        }
        //3生成token
        LoginAppUser loginAppUser = new LoginAppUser(appUser.getUserId(), appUser);
        recordLoginInfo(loginAppUser.getUserId());
        return appTokenService.createAppToken(loginAppUser);
    }

    /**
     * 获取手机号
     * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
     *
     * @param code
     * @return
     */
    public String getPhoneNumber(String code) {
        logger.info("获取 code: {}", code);
        JSONObject accessToken = weChatUserInfoUtilService.getAccessToken(appId, appSecret);
        logger.info("小程序登录获取 accessToken: {}", accessToken.toJSONString());
        JSONObject jsonObject = weChatUserInfoUtilService.getPhoneNumber(code, accessToken.getString("access_token"));
        if (jsonObject.getInteger("errcode") != 0) {
            log.error(String.format("获取微信授权信息失败，错误编码：%s，错误信息：%s", String.valueOf(jsonObject.get("errcode")), (String) jsonObject.get("errmsg")));
            throw new ServiceException(String.format("获取微信授权信息失败，错误编码：%s，错误信息：%s", String.valueOf(jsonObject.get("errcode")), (String) jsonObject.get("errmsg")));
        }
        JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
        //没有区号的手机号
        String purePhoneNumber = phoneInfo.getString("purePhoneNumber");
        return purePhoneNumber;
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    private void recordLoginInfo(Long userId) {
        AppUser appUser = new AppUser();
        appUser.setUserId(userId);
        appUser.setLoginIp(IpUtils.getIpAddr());
        appUser.setLoginDate(DateUtils.getNowDate());
        appUserSevice.updateAppUser(appUser);
    }

    /**
     * 设置用户身份信息
     *
     * @param appUser
     */
    public void setLoginAppUser(LoginAppUser loginAppUser, AppUser appUser) {
        loginAppUser.setAppUser(appUser);
        appTokenService.setUserAgent(loginAppUser);
        appTokenService.refreshToken(loginAppUser);
    }


}
